#ifndef GAME_OPENGL_H
#define GAME_OPENGL_H
#include "game.h"
#include <windows.h>
#include "gl/GL.h"

#define GL_FRAMEBUFFER_SRGB 0x8DB9
#define GL_SRGB8_ALPHA8 0x8C43
#define GL_FRAMEBUFFER 0x8D40
#define GL_COLOR_ATTACHMENT0 0x8CE0
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5

// 在 <*attribList> 中被接受作为一个属性名。
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_LAYER_PLANE_ARB 0x2093
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126

#define WGL_CONTEXT_DEBUG_BIT_ARB 0x0001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x0002

#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002

#define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096

#define GL_SHADING_LANGUAGE_VERSION 0x8B8C

typedef void WINAPI gl_Bind_Framebuffer(GLenum target, GLuint framebuffer);
typedef void WINAPI gl_Delete_Framebuffers(GLsizei n, const GLuint* framebuffers);
typedef void WINAPI gl_Gen_Framebuffers(GLsizei n, GLuint* framebuffers);
typedef void WINAPI gl_Framebuffer_Texture_2D(GLenum target, GLenum attachment, GLenum textarget,
                                              GLuint texture, GLint level);
typedef GLenum WINAPI gl_Check_Framebuffer_Status(GLenum target);

extern gl_Bind_Framebuffer* glBindFramebuffer;
extern gl_Delete_Framebuffers* glDeleteFramebuffers;
extern gl_Gen_Framebuffers* glGenFramebuffers;
extern gl_Framebuffer_Texture_2D* glFramebufferTexture2D;
extern gl_Check_Framebuffer_Status* glCheckFramebufferStatus;

struct opengl_info {
    bool32 ModernContext;
    char* Vendor;
    char* Renderer;
    char* Version;
    const char* ShadingLanguageVersion;
    char* Extensions;
    bool32 GL_EXT_texture_sRGB_decode;
    bool32 GL_ARB_framebuffer_sRGB;
    bool32 GL_ARB_framebuffer_object;
};

struct texture_op_allocate {
    uint32 Width;
    uint32 Height;
    void* Data;
    void** ResultHandle;
};
struct texture_op_deallocate {
    void* Handle;
};
struct texture_op {
    texture_op* Next;
    bool32 IsAllocate;
    union {
        texture_op_allocate Allocate;
        texture_op_deallocate Deallocate;
    };
};

opengl_info OpenGLGetInfo(bool32 ModernContext);
opengl_info OpenGLInit(bool32 ModernContext, bool32 FrameBufferSupportsSRGB);
extern GLuint OpenGLDefaultInternalTextureFormat;
void OpenGLRenderCommands(game_render_commands* Commands, game_render_prep* Prep,
                          rectangle2i DrawRegion, uint32 WindowWidth, uint32 WindowHeight);
void OpenGLDisplayBitmap(int32 Width, int32 Height, void* Memory, int32 Pitch,
                         rectangle2i DrawRegion, v4 ClearColor, GLuint BlitTexture);
void OPenGLLineVertices(v2 MinP, v2 MaxP);
void OpenGLBindFramebuffer(uint32 TargetIndex, rectangle2i DrawRegion);
void OpenGLManageTexture(texture_op* First);
#endif